//REQUIRED CLASS
package project4;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;

import com.sun.org.apache.xalan.internal.xsltc.compiler.Pattern;

import project1.*;
import project2.*;

public class Database extends  HashMap<String, Relation>
{
	private DatalogProgram dp;
	public static HashMap<String,Integer> freeVariables = new HashMap<String, Integer>();
	
	public Database(DatalogProgram dp){
		this.dp = dp;
		//Create Schemes
		//Creates Tables for the Database
		for (Scheme s : dp.getSchemes()){
			for(int i=0;i<s.getAttrList().size();i++){
				s.getAttrList().set(i, s.getAttrList().get(i)+"_org");
			}
			this.put(s.getSchemeName(), new Relation(s.getSchemeName(),s.getAttrList()));
		}
		//Loop through each Fact
		//Populate the tables of the database
		for (Fact f : dp.getFacts()){
			Tuple tuple = this.get(f.getFactName()).tuple;
			//For each fact, Loop through arguments and add to tuple
			TupleHashMap tempHashMap = new TupleHashMap(this.get(f.getFactName()).getSchema());
			int i = 0;
			for (String c : f.getConstList()){
				tempHashMap.put(this.get(f.getFactName()).getSchema().get(i), c);
				i++;
			}
			tuple.add(tempHashMap);
		}
		this.Evaluate();
	}
	
	
	
	
	@SuppressWarnings("rawtypes")
	public boolean Evaluate(){
		//Loop through each Query and Evaluate
		for(Query q : dp.getQueries()){
			freeVariables=new HashMap<String, Integer>();
			int i = 0;
			Relation baseRelation = this.clone(this.get(q.getQueryName()));
			//Loops through query arguments
			//Renames
			ArrayList<String> newname = new ArrayList<String>();
			for (String s : baseRelation.getSchema()){
				newname.add(s);
			}
			int j =0;
			for(String s: q.getArg()){
				//If it's not a string and is actually a keyword
				if (!checkIfString(s)){
					freeVariables.put(s, 1);
					newname.set(j, s);
				}
				j++;
			}
			baseRelation = baseRelation.rename(newname);
			
			
			
			for(String s : q.getArg()){
				//Creates a sub relation with a select statement (gets variable based off of position, value)
				if (checkIfString(s))
					baseRelation = baseRelation.select(baseRelation.getSchema().get(i), s);
				i++;
			}
			System.out.print(q.toString());
			TreeSet<HashMap> temptree = new TreeSet<HashMap>(baseRelation.tuple);
			//baseRelation.tuple.eliminateDuplicates();
			if(temptree.size()>0)
				System.out.print(" Yes("+temptree.size()+")\n");
			else
				System.out.print(" No\n");
			if(!baseRelation.toString().equals(""))
				System.out.print(baseRelation.toString());
		}
		return false;
	}
	private ArrayList<String> findRenames(ArrayList<String> args){
		for(String s : args){
			
		}
		
		return args;
		
	}
	private boolean checkIfString(String queryString){
		 return queryString.matches("\'.*\'");
	}
	private Relation clone(Relation oldRelation){
		Relation newrelation = new Relation(oldRelation.getSchemeName(),oldRelation.getSchema());

		newrelation.tuple = (Tuple)oldRelation.tuple.clone();
		
		return newrelation;
	}

}
